<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Multimodal Search & Capture UI</title>
    <link href="/sdk/javascript/bootstrap.min.css" rel="stylesheet" />
    <style>
      video,
      canvas {
        border: 1px solid #ccc;
        margin-bottom: 10px;
      }
      .result-card {
        border: 1px solid #ddd;
        border-radius: 8px;
        padding: 10px;
        margin-bottom: 15px;
        background: #f9f9f9;
      }
      .image-preview {
        max-width: 100%;
        max-height: 150px;
        object-fit: cover;
        border-radius: 4px;
      }
    </style>
    <script src="/sdk/javascript/nanosdk.min.js"></script>
  </head>
  <body class="p-4">
    <div class="container-fluid">
      <div class="row">
        <!-- 📸 Left Panel: Camera Capture -->
        <div class="col-md-6">
          <h4>📷 Automatic Camera Capture</h4>
          <video id="video" autoplay playsinline width="100%"></video>
          <canvas
            id="canvas"
            width="640"
            height="480"
            style="display: none"
          ></canvas>
          <button id="toggleBtn" class="btn btn-primary mt-2">
            ⏯️ Start Capture
          </button>
          <pre
            id="log"
            class="mt-3 bg-light p-2"
            style="height: 200px; overflow-y: auto"
          ></pre>
        </div>

        <!-- 🔍 Right Panel: Search -->
        <div class="col-md-6">
          <h4>🔎 Search Images (Prompt / Image / Both)</h4>
          <form id="searchForm">
            <div class="mb-2">
              <label for="prompt" class="form-label">Prompt</label>
              <input
                type="text"
                id="prompt"
                class="form-control"
                placeholder="e.g. orange dog"
              />
            </div>
            <div class="mb-2">
              <label for="imageFile" class="form-label">Image file</label>
              <input
                type="file"
                id="imageFile"
                class="form-control"
                accept="image/*"
              />
            </div>
            <button type="submit" class="btn btn-success">🔍 Search</button>
          </form>

          <div class="mt-4">
            <h6>Results:</h6>
            <div id="results" class="row row-cols-1 g-3"></div>
          </div>
        </div>
      </div>
    </div>

    <script>
      document.addEventListener("DOMContentLoaded", function () {
        const video = document.getElementById("video");
        const canvas = document.getElementById("canvas");
        const ctx = canvas.getContext("2d");
        const log = document.getElementById("log");
        const toggleBtn = document.getElementById("toggleBtn");

        const host = "http://localhost:4000";
        const token = "";

        const base_description =
          "Marco's office in the [[time]], with a laptop and working.";

        const client = new NanoSDK().createHttpClient(host, token);

        // Start webcam
        async function startCamera() {
          try {
            const stream = await navigator.mediaDevices.getUserMedia({
              video: true,
            });
            video.srcObject = stream;
            logMessage("✅ Camera started.");
          } catch (err) {
            logMessage("❌ Error: " + err.message);
          }
        }

        function captureImageBase64() {
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
          const base64 = canvas.toDataURL("image/jpeg");
          logMessage("📸 Captured. Simulating send...");

          try {
            mockSendToBackend(base64);
          } catch (error) {
            logMessage("❌ Error: " + error.message);
          }
        }

        function toggleCapture() {
          captureImageBase64();
        }

        async function mockSendToBackend(base64) {
          try {
            // Generate vector embedding
            const currentDescription = await updateDescription(base64);
            const inputs = {
              image_base64: base64,
              description: currentDescription,
            };

            const response = await client.python3("embedding-clip", inputs);

            // Save image

            const inputs2 = {
              base64: base64,
              dir_path:
                "${process.env.WORKFLOWS_PATH.replace('workflows', 'public')}",
            };

            const response2 = await client.nodejs("save-image", inputs2);

            // Save vector text and image in Milvus
            const inputs3 = {
              text_vector: response.data.text_vector,
              image_vector: response.data.image_vector,
              description: currentDescription,
              image_url: response2.data.url_path,
            };
            await client.python3("store-in-milvus", inputs3);
          } catch (error) {
            logMessage("❌ Error: " + error.message);
          }

          logMessage(
            "✅ Mock sent. Base64 starts with: " + base64.substring(0, 10)
          );
        }

        // Function to get the current time period (morning/afternoon/evening) with actual time
        async function updateDescription(imageBase64) {
          const responseDesc = await client.python3("image-description", {
            image_base64: imageBase64,
          });

          return `${responseDesc.data.description} - ${getCurrentTimePeriod()}`;
        }

        function getCurrentTimePeriod() {
          const now = new Date();
          const hours = now.getHours();
          let timePeriod;

          if (hours >= 5 && hours < 12) {
            timePeriod = "morning";
          } else if (hours >= 12 && hours < 17) {
            timePeriod = "afternoon";
          } else {
            timePeriod = "evening";
          }

          // Format hours to 12-hour format
          let displayHours = hours % 12;
          if (displayHours === 0) displayHours = 12;

          // Get minutes with leading zero if needed
          const minutes = now.getMinutes().toString().padStart(2, "0");

          // Determine AM or PM
          const ampm = hours >= 12 ? "pm" : "am";

          return `${timePeriod} at ${displayHours}:${minutes}${ampm}`;
        }

        function logMessage(msg) {
          const time = new Date().toLocaleTimeString();
          log.textContent = `[${time}] ${msg}\n` + log.textContent;
        }

        toggleBtn.addEventListener("click", async () => await toggleCapture());
        startCamera();

        function convertImageToBase64Sync(file) {
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result);
            reader.onerror = (error) => reject(error);
            reader.readAsDataURL(file);
          });
        }

        // Search form
        document
          .getElementById("searchForm")
          .addEventListener("submit", async function (e) {
            e.preventDefault();

            const prompt = document.getElementById("prompt").value;
            let inputs = {};
            let promptText = true;
            let promptImage = true;

            if (!prompt || prompt === "") {
              promptText = false;
            }
            else {
              inputs.description = prompt;
            }

            const files = document.getElementById("imageFile").files;
            if (files.length !== 0) {
              const imageFile = document.getElementById("imageFile").files[0];
              let imageBase64 = await convertImageToBase64Sync(imageFile);
              inputs.image_base64 = imageBase64;

              if (!inputs.description) {
                inputs.description = "";
              }
            } else {
              promptImage = false;
            }

            if (!inputs.description && !inputs.image_base64) {
              logMessage("❌ Please provide a prompt or an image.");
              return;
            }

            const response = await client.python3("embedding-clip", inputs);

            // Search in Milvus
            const inputs2 = {
              top_k: 5,
            };

            if (promptText) {
              inputs2.text_vector = response.data.text_vector;
            }

            if (promptImage) {
              inputs2.image_vector = response.data.image_vector;
            }

            const response2 = await client.python3("search-in-milvus", inputs2);

            const resultsContainer = document.getElementById("results");
            resultsContainer.innerHTML = ""; // Clear previous

            const results = response2.data.results;
            if (response2.data.error) {
              logMessage("❌ Error: " + response2.data.error);
              return;
            }
            if (results.length === 0) {
              logMessage("❌ No results found.");
              return;
            }

            let totalScore = 0;

            results.forEach((res) => {
              if (res.score >= 0.5) {
                const col = document.createElement("div");
                col.className = "col";

                col.innerHTML = `
                  <div class="result-card">
                    <img src="${
                      res.image_url
                    }" class="image-preview mb-2" alt="result" />
                    <div><strong>${res.description}</strong></div>
                    <small class="text-muted">Score: ${res.score.toFixed(
                      2
                    )}</small>
                  </div>
                `;
                resultsContainer.appendChild(col);
                totalScore += res.score;
              }
            });

            logMessage(
              `✅ Search completed. Total results: ${totalScore.toFixed(2)}`
            );
          });
      });
    </script>
  </body>
</html>
